#include <string.h>

#include "lib.h"

#include "striter.h"
#include "opthelpr.h"

StraightIter::StraightIter(uint8* counts)
{
	this->counts = counts;
}

int32
StraightIter::getStartRank()
{
	ASSERT(start >= counts && start < counts + 13);

	return RANKPTR(start);
}

bool8
StraightIter::findStraight(bool8 allowJoker, bool8 firstTime)
{
	while (findRun(allowJoker, firstTime))
	{
		if (runLen >= 5)
			return true;

		firstTime = false;
	}
	return false;
}

bool8
StraightIter::findRun(bool8 allowJoker, bool8 firstTime)
{
	if (firstTime)
	{
		if (firstRun(allowJoker))
			return true;
	}
	else
	{
		if (nextRun(allowJoker))
			return true;

		else if ((flags & SI_ACEDONE) == 0)
		{
			flags |= SI_ACEDONE;

			if (aceLowRun(allowJoker))
			{
				start = counts + COUNTNDX(ACERANK);		// signal special case

				return true;
			}
		}
	}

	return false;
}

bool8
StraightIter::firstRun(bool8 allowJoker)
{
	flags = 0;
	wild = probe = (uint8*)0;

	start = skipZeros(counts, 13);

	if (start)
	{
		if (allowJoker && HASJOKER())
		{
			insertWild();	// might set SI_NORMALDONE
			findEnd();		// modifies probe
			*wild = 0;
		}
		else
			findEnd();		// modifies probe

		return true;
	}

	flags |= (SI_NORMALDONE | SI_ACEDONE);

	return false;
}

bool8
StraightIter::nextRun(bool8 allowJoker)
{
	if (flags == 0)
	{
		if (allowJoker && HASJOKER())
		{
			ASSERT(wild != (uint8*)0);

			probe = wild;
			wild = (uint8*)0;
			start = skipMoreZeros(probe);

			if (start)
			{
				insertWild();	// might set SI_NORMALDONE
				findEnd();		// modifies probe
				*wild = 0;

				return true;
			}
		}
		else
		{
			ASSERT(probe != (uint8*)0);

			start = skipMoreZeros(probe);// probe already points past last non-0

			if (start)
			{
				findEnd();		// modifies probe

				return true;
			}
		}
	}

	flags |= SI_NORMALDONE;

	return false;
}

bool8
StraightIter::aceLowRun(bool8 allowJoker)
{
	if (allowJoker && HASJOKER())
	{
		if (HASACE())
		{
			// insert wild into 2 thru xxx sequence
			//
			start = probe = counts;
			wild = (uint8*)0;

			insertWild();

			findEnd();

			*wild = 0;
		}
		else
		{
			start = probe = counts;

			wild = counts + COUNTNDX(ACERANK);

			findEnd();
		}

		++runLen;	// include ACE in length (it may really be the joker)

		return true;
	}
	else if (HASACE())
	{
		start = probe = counts;

		findEnd();

		++runLen;	// include ACE in length

		return true;
	}
	return false;
}

void
StraightIter::insertWild()
{
	ASSERT(start != (uint8*)0 && wild == (uint8*)0);

	probe = start;
	while (probe < counts + 13)
	{
		if (*probe == 0)
		{
			wild = probe;
			*probe = 1;
			break;
		}
		++probe;
	}

	if (!wild)
	{
		probe = start - 1;
		while (probe >= counts)
		{
			if (*probe == 0)
			{
				wild = start = probe;
				*probe = 1;
				break;
			}
			--probe;
		}

		flags |= SI_NORMALDONE;
	}
}

void
StraightIter::findEnd()
{
	ASSERT(start >= counts && start < counts + 13);

	runLen = 0;
	probe = start;

	while (probe < counts + 13 && *probe)
	{
		++runLen;
		++probe;
	}

	//
	// probe points 1 item past the last non-zero item
	//
}
